home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 April
/
EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso
/
EARCD
/
util
/
pack
/
xpk_Source.lha
/
xpk_Source
/
xpkmaster
/
open.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-26
|
10KB
|
353 lines
#ifndef XPKMASTER_OPEN_C
#define XPKMASTER_OPEN_C
/* Routinesheader
Name: open.c
Main: xpkmaster
Versionstring: $VER: open.c 1.1 (28.10.96)
Author: SDI
Distribution: PD
Description: Opening and initialisation routines for XPK files
1.0 06.10.96 : first real version
1.1 28.10.96 : reincluded A4 support
*/
#include <exec/types.h>
#include <dos/dos.h>
#include <pragma/exec_lib.h>
#include <pragma/dos_lib.h>
#include "xpkmaster.h"
#include "xpk_strings.h"
static LONG getinlen(struct XpkBuffer *xbuf);
#define ROW_OF_MINUS 0x2d2d2d2d /* '----' */
#define PP_COOKIE 0x50503230 /* 'PP20' */
LONG __asm xpkopen(register __a0 struct XpkBuffer **xbufp,
register __a1 struct TagItem *tags, register __d2 ULONG examine A4PROTO)
{
struct Library *XpkSubBase;
struct XpkBuffer *xbuf;
struct XpkStreamHeader *globhdr;
struct XpkFib *fib;
LONG res;
LONG bytesread; /* used to be able to reset after a short read */
#if defined(DEBUG) && defined(SUPPORT_A4)
DebugRunTime("xpkopen: A4 = %ld", a4);
#elif defined (DEBUG)
DebugRunTime("xpkopen");
#endif
*xbufp = 0;
if(!(xbuf = initxbuf()))
{
parseerrortags(tags);
return XPKERR_NOMEM;
}
#ifdef SUPPORT_A4
xbuf->xb_regA4 = a4;
#endif
globhdr = &xbuf->xb_Headers.h_Glob;
fib = &xbuf->xb_Fib;
if(parsebuftags(xbuf, tags, 0))
goto Abort;
*xbufp = xbuf;
if(xbuf->xb_Flags & XMF_PACKING)
return xpkopenwrite(xbufp, tags);
if(!hookread(xbuf, XIO_READ, globhdr, 4))
{ /* Read first longword only */
bytesread = xbuf->xb_InLen = xbuf->xb_RMsg.xmm_Size;
if(xbuf->xb_Result == XPKERR_TRUNCATED)
goto Uncompressed;
else
goto Abort;
}
else
bytesread = 4;
/**************************** Standard XPK file *********************/
if(globhdr->xsh_Pack == XPK_COOKIE)
{ /* Standard XPK packed files */
UWORD exthlen = 0; /* size of extended header if present */
xbuf->xb_Format = XPKMODE_UPSTD;
/* Read rest of the global header */
if(!hookread(xbuf, XIO_READ, (STRPTR) globhdr + 4, sizeof(struct XpkStreamHeader) - 4))
goto Abort;
if(hchecksum((STRPTR) globhdr, sizeof(struct XpkStreamHeader)))
{
xbuf->xb_Result = XPKERR_CHECKSUM;
goto Abort;
}
if(!examine && globhdr->xsh_Flags & XPKSTREAMF_PASSWORD &&
!xbuf->xb_Password)
{
xbuf->xb_Result = XPKERR_NEEDPASSWD;
goto Abort;
}
if(globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS)
xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrLong);
else
xbuf->xb_Headers.h_LocSize = sizeof(struct XpkChunkHdrWord);
if(globhdr->xsh_Flags & XPKSTREAMF_EXTHEADER)
{
if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
goto Abort;
if(!hookread(xbuf, XIO_READ, NULL, exthlen))
goto Abort;
exthlen += sizeof(UWORD); /* for unwinding while XpkExamine */
}
if(!hookread(xbuf, XIO_READ, &xbuf->xb_Headers.h_Loc,
xbuf->xb_Headers.h_LocSize)) /* first lochdr */
goto Abort;
xbuf->xb_Fib.xf_CCur = sizeof(struct XpkStreamHeader);
updatefib(xbuf);
if(!(xbuf->xb_SubBase = XpkSubBase = opensub(xbuf, globhdr->xsh_Type)))
goto Abort;
if(globhdr->xsh_SubVrs > xbuf->xb_SubInfo->xi_LibVersion)
{
xbuf->xb_Result = XPKERR_OLDSUBLIB;
goto Abort;
}
xbuf->xb_ULen = globhdr->xsh_ULen;
xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_UnpackMsg ?
xbuf->xb_SubInfo->xi_UnpackMsg : strings[TXT_UNPACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_UnpackedMsg ?
xbuf->xb_SubInfo->xi_UnpackedMsg : strings[TXT_UNPACKED];
if(globhdr->xsh_Flags & XPKSTREAMF_PASSWORD)
xbuf->xb_Fib.xf_Flags |= XPKFLAGS_PASSWORD;
if(examine && !hookread(xbuf, XIO_SEEK, 0,
-(sizeof(struct XpkStreamHeader) + xbuf->xb_Headers.h_LocSize+exthlen)))
goto Abort;
goto Exit;
}
if(xbuf->xb_InLen == -1)
{
if((res = getinlen(xbuf)))
{
xbuf->xb_Result = res;
goto Abort;
}
}
#ifdef USE_POWERPACKER
/***************************** PowerPacker file ***********************/
if(globhdr->xsh_Pack == PP_COOKIE)
{
struct Library *PPBase;
LONG outsize;
xbuf->xb_Format = XPKMODE_UPPP;
if(!hookread(xbuf, XIO_SEEK, 0, xbuf->xb_InLen - 8))
goto Abort; /* 4 Bytes before EOF */
if(!hookread(xbuf, XIO_READ, &outsize, 4))
goto Abort;
if(!hookread(xbuf, XIO_SEEK, 0, - (xbuf->xb_InLen - 4 + (examine << 2))))
goto Abort;
outsize >>= 8;
fib->xf_Type = XPKTYPE_PACKED;
fib->xf_CLen = xbuf->xb_InLen;
fib->xf_ULen = outsize;
fib->xf_NLen = outsize + XPK_MARGIN;
fib->xf_ID = PP_COOKIE;
percentages (fib);
if(examine)
goto Exit;
xbuf->xb_Prog.xp_Activity = strings[TXT_UNPACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = "PowerPacker";
xbuf->xb_LastMsg = strings[TXT_UNPACKED];
xbuf->xb_ULen = outsize;
if(!(PPBase = OpenLibrary ("powerpacker.library", 0)))
{
xbuf->xb_Result = XPKERR_MISSINGLIB;
goto Abort;
}
xbuf->xb_SubBase = PPBase;
goto Exit;
}
#endif /* USE_POWERPACKER */
/* Future Code
if((WORD) globhdr->xsh_Pack == 0x1F9D)
{ // UNIX compress
}
*/
/**************************** Uncompressed file *************************/
Uncompressed:
if(examine || xbuf->xb_Flags & XMF_PASSTHRU) /* Unpacked */
{
xbuf->xb_Format = XPKMODE_UPUP;
fib->xf_Type = XPKTYPE_UNPACKED;
fib->xf_CLen = xbuf->xb_InLen;
fib->xf_ULen = xbuf->xb_InLen;
fib->xf_NLen = Min(CHUNKSIZE, xbuf->xb_InLen) + XPK_MARGIN;
fib->xf_ID = ROW_OF_MINUS;
xbuf->xb_Prog.xp_Activity = strings[TXT_READING];
xbuf->xb_Prog.xp_PackerName = "MASTER";
xbuf->xb_LastMsg = strings[TXT_READ];
xbuf->xb_ULen = xbuf->xb_InLen;
xbuf->xb_Result = XPKERR_OK; /* if != 0 is was XPKERR_TRUNCATED */
if(!hookread(xbuf, XIO_SEEK, 0, -bytesread))
goto Abort;
goto Exit;
}
xbuf->xb_Result = XPKERR_NOTPACKED; /* Can't unpack, can't passthru */
Abort:
*xbufp = 0;
return XpkClose(xbuf);
Exit:
*xbufp = xbuf;
return XPKERR_OK;
}
/****************************** Open for packing **************************/
LONG xpkopenwrite(struct XpkBuffer **xbufp, struct TagItem *tags)
{
struct XpkBuffer *xbuf = *xbufp;
struct XpkStreamHeader *globhdr = &xbuf->xb_Headers.h_Glob;
struct Library *XpkSubBase;
LONG res;
xbuf->xb_Format = XPKMODE_PKSTD;
if(getinlen(xbuf)) /* Find InLen */
{
xbuf->xb_Result = XPKERR_BADPARAMS;
goto Abort;
}
if(!(XpkSubBase = xbuf->xb_SubBase)) /* Do we know the sublib? */
{
xbuf->xb_Result = XPKERR_BADPARAMS;
goto Abort;
}
xbuf->xb_MinChunk = xbuf->xb_SubInfo->xi_MinPkInChunk;
if(xbuf->xb_Password && !(xbuf->xb_SubInfo->xi_Flags & XPKIF_ENCRYPTION))
{
xbuf->xb_Result = XPKERR_NOCRYPT;
goto Abort;
}
if(!xbuf->xb_Password && xbuf->xb_SubInfo->xi_Flags & XPKIF_NEEDPASSWD)
{
xbuf->xb_Result = XPKERR_NEEDPASSWD;
goto Abort;
}
if(!(xbuf->xb_Flags & XMF_LOSSYOK) &&
xbuf->xb_SubInfo->xi_Flags & XPKIF_LOSSY)
{
xbuf->xb_Result = XPKERR_LOSSY;
goto Abort;
}
if(xbuf->xb_PackingMode > 100) /* Is packing mode valid? */
xbuf->xb_PackingMode = 100; /* Use max */
if(!hookwrite(xbuf, XIO_TOTSIZE, 0,
(xbuf->xb_InLen + xbuf->xb_InLen / 32 & ~3) + 2 * XPK_MARGIN))
goto Abort;
/*********************** Find the chunk size *********************/
if((xbuf->xb_ChunkSize == 0) &&
((xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_DefPkInChunk) == 0))
xbuf->xb_ChunkSize = DEFAULTCHUNKSIZE;
if(xbuf->xb_ChunkSize < xbuf->xb_SubInfo->xi_MinPkInChunk)
xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MinPkInChunk;
if((xbuf->xb_SubInfo->xi_MaxPkInChunk) &&
(xbuf->xb_ChunkSize > xbuf->xb_SubInfo->xi_MaxPkInChunk))
xbuf->xb_ChunkSize = xbuf->xb_SubInfo->xi_MaxPkInChunk;
/******************* Prepare global header *********************/
globhdr->xsh_Pack = 0; /* Initialize the global header */
globhdr->xsh_Type = xbuf->xb_SubID;
if(xbuf->xb_ChunkSize > 65000)
globhdr->xsh_Flags |= XPKSTREAMF_LONGHEADERS;
if(xbuf->xb_Password)
globhdr->xsh_Flags |= XPKSTREAMF_PASSWORD;
xbuf->xb_Headers.h_LocSize = globhdr->xsh_Flags & XPKSTREAMF_LONGHEADERS
? sizeof (struct XpkChunkHdrLong)
: sizeof (struct XpkChunkHdrWord);
memset(globhdr->xsh_Initial, 0xff, 16); /* Read first 16 bytes */
xbuf->xb_Prog.xp_Activity = xbuf->xb_SubInfo->xi_PackMsg ?
xbuf->xb_SubInfo->xi_PackMsg : strings[TXT_PACKING_UPPER];
xbuf->xb_Prog.xp_PackerName = xbuf->xb_SubInfo->xi_Name;
xbuf->xb_LastMsg = xbuf->xb_SubInfo->xi_PackedMsg ?
xbuf->xb_SubInfo->xi_PackedMsg : strings[TXT_PACKED];
Abort:
xbuf->xb_Fib.xf_NLen = Min(xbuf->xb_InLen - xbuf->xb_Fib.xf_UCur,
xbuf->xb_ChunkSize);
if((res = xbuf->xb_Result))
res = XpkClose(xbuf);
return res;
}
static LONG getinlen(struct XpkBuffer *xbuf)
{
if(xbuf->xb_InLen == -1)
{
if(xbuf->xb_RHook == &fhinhook)
{ /* For files, find length from here to end */
LONG opos;
if((opos = Seek(xbuf->xb_RMsg.xmm_FH, 0, OFFSET_END)) < 0 ||
(xbuf->xb_InLen=Seek(xbuf->xb_RMsg.xmm_FH, opos,OFFSET_BEGINNING)) <0)
return XPKERR_IOERRIN;
}
else if(xbuf->xb_RHook == &meminhook) /* InLen always required for input from memory */
return XPKERR_BADPARAMS;
/* For unpacking from custom hooks, InLen is only needed for PowerPacker */
}
return 0;
}
#endif /* XPKMASTER_OPEN_C */